package pl.edu.pw.stud.ltrzaska.mvc.controller;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Method;
import java.util.ArrayList;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import pl.edu.pw.stud.ltrzaska.mvc.model.AbstractModel;
import pl.edu.pw.stud.ltrzaska.mvc.view.AbstractViewPanel;

public abstract class AbstractController implements PropertyChangeListener, Runnable {
	private static final Logger LOGGER = Logger.getLogger(AbstractController.class);
	private ArrayList<AbstractViewPanel> registeredViews;
	private ArrayList<AbstractModel> registeredModels;

	public AbstractController() {
		registeredViews = new ArrayList<AbstractViewPanel>();
		registeredModels = new ArrayList<AbstractModel>();
	}

	public void addModel(AbstractModel model) {
		registeredModels.add(model);
		model.addPropertyChangeListener(this);
	}

	public void removeModel(AbstractModel model) {
		registeredModels.remove(model);
		model.removePropertyChangeListener(this);
	}

	public void addView(AbstractViewPanel view) {
		registeredViews.add(view);
	}

	public void removeView(AbstractViewPanel view) {
		registeredViews.remove(view);
	}

	public void propertyChange(PropertyChangeEvent evt) {
		for (AbstractViewPanel view : registeredViews) {
			view.modelPropertyChange(evt);
		}
	}

	protected void setModelProperty(String propertyName, Object newValue) {
		String cName = StringUtils.capitalize(propertyName);
		for (AbstractModel model : registeredModels) {
			try {
				Method method = model.getClass().getMethod("set" + cName,
						new Class[] { newValue.getClass() });
				method.invoke(model, newValue);
			} catch (NoSuchMethodException e) {
				LOGGER.error("There is no method set" + cName + "in model", e);
			} catch (Exception e) {
				LOGGER.error("", e);
			}
		}
	}

	protected Object getModelProperty(String propertyName) {
		String cName = StringUtils.capitalize(propertyName);
		Object ret = null;
		try {
			for (AbstractModel model : registeredModels) {
				Method method = model.getClass().getMethod("get" + cName);
				ret = method.invoke(model);
				System.out.println("Method:" + ret);
			}
		} catch (NoSuchMethodException e) {
			LOGGER.error("There is no method get" + cName + "in model", e);
		} catch (Exception e) {
			LOGGER.error("", e);
		}
		return ret;
	}
	

	public void numViews() {
		LOGGER.debug("num registered views: " + registeredViews.size());
	}
}
